# -*- coding: utf-8 -*-
#
from __future__ import division

import numpy
import sympy

from ..helpers import untangle


class Dunavant(object):
    '''
    D.A. Dunavant,
    Economical symmetrical quadrature rules for complete polynomials over a
    square domain,
    Numerical Methods in Engineering, Volume 21, Issue 10, October 1985,
    Pages 1777–1784,
    <https://doi.org/10.1002/nme.1620211004>.

    Abstract:
    It is of interest in numerical analysis to develop symmetrical quadrature
    rules for integration of complete polynomial functions over a square domain
    with minimum computational effort. Gaussian product quadrature rules
    integrate such functions with maximum effort. Symmetrical quadrature rules
    are developed and presented for integration of complete polynomial
    functions up to 21st order with minimum computational effort.
    '''
    def __init__(self, index, symbolic=False):
        frac = sympy.Rational if symbolic else lambda x, y: x/y
        sqrt = sympy.sqrt if symbolic else numpy.sqrt

        if index == 0:
            self.degree = 1
            data = [(4, numpy.array([[0, 0]]))]
        elif index == 1:
            self.degree = 3
            data = [(1, _symm_s(sqrt(frac(1, 3))))]
        elif index == 2:
            self.degree = 5
            data = [
                (frac(40, 49), _symm_r_0(sqrt(frac(7, 15)))),
                (frac(9, 49), _symm_s(sqrt(frac(7, 9)))),
                ]
        elif index == 3:
            self.degree = 7
            data = [
                (frac(98, 405), _symm_r_0(sqrt(frac(6, 7)))),
                (0.237431774690630, _symm_s(0.805979782918599)),
                (0.520592916667394, _symm_s(0.380554433208316)),
                ]
        elif index == 4:
            self.degree = 9
            data = [
                (0.018475842507491, _symm_r_0(1.121225763866564)),
                (0.390052939160735, _symm_r_0(0.451773049920657)),
                (0.083095178026482, _symm_s(0.891849420851512)),
                (0.254188020152646, _st(0.824396370749276, 0.411623426336542)),
                ]
        elif index == 5:
            self.degree = 11
            data = [
                (0.365379525585903, _c()),
                (0.027756165564204, _symm_r_0(1.044402915409813)),
                (0.244272057751754, _symm_r_0(0.769799068396649)),
                (0.034265103851229, _symm_s(0.935787012440540)),
                (0.308993036133713, _symm_s(0.413491953449114)),
                (0.146684377651312, _st(0.883025508525690, 0.575653595840465)),
                ]
        elif index == 6:
            self.degree = 13
            data = [
                (0.005656169693764, _symm_r_0(1.086056158573971)),
                (0.192443867470396, _symm_r_0(0.658208197042585)),
                (0.005166832979773, _symm_s(1.001300602991729)),
                (0.200302559622138, _symm_s(0.584636168775946)),
                (0.228125175912536, _symm_s(0.246795612720261)),
                (0.117496926974491, _st(0.900258815287201, 0.304720678579870)),
                (0.066655770186205, _st(0.929866705560780, 0.745052720131169)),
                ]
        elif index == 7:
            self.degree = 15
            data = [
                (-0.001768979827207, _c()),
                (+0.012816726617512, _symm_r_0(1.027314357719367)),
                (+0.119897873101347, _symm_r_0(0.856766776147643)),
                (+0.210885452208801, _symm_r_0(0.327332998189723)),
                (+0.006392720128215, _symm_s(0.967223740028505)),
                (+0.104415680788580, _symm_s(0.732168901749711)),
                (0.168053047203816, _st(0.621974427996805, 0.321696694921009)),
                (0.076169694452294, _st(0.928618480068352, 0.455124178121179)),
                (0.028794154400064, _st(0.960457474887516, 0.809863684081217)),
                ]
        elif index == 8:
            self.degree = 17
            data = [
                (0.020614915919991, _symm_r_0(0.989353074512600)),
                (0.128025716179910, _symm_r_0(0.376285207157973)),
                (0.005511739534032, _symm_s(0.978848279262233)),
                (0.039207712457142, _symm_s(0.885794729164116)),
                (0.076396945079863, _symm_s(0.171756123838348)),
                (0.141513729949972, _st(0.590499273806002, 0.319505036634574)),
                (0.083903279363798, _st(0.799079131916863, 0.597972451929457)),
                (0.060394163649685, _st(0.803743962958745, 0.058344481776551)),
                (0.057387752969213, _st(0.936506276127495, 0.347386316166203)),
                (0.021922559481864, _st(0.981321179805452, 0.706000287798646)),
                ]
        elif index == 9:
            # TODO ERR the article claims 19
            self.degree = 16
            data = [
                (0.038205406871462, _symm_r_0(0.943962831808239)),
                (0.135368502976521, _symm_r_0(0.536918434376013)),
                (0.005773708558664, _symm_s(0.973981076394170)),
                (0.067460759759473, _symm_s(0.742995535327609)),
                (0.140899115227892, _symm_s(0.285010052188916)),
                (0.047466627685662, _symm_s(0.068354569272491)),
                (0.078619467342982, _st(0.802952004398543, 0.203345534163332)),
                (0.094979169511394, _st(0.634244672807882, 0.426572172992877)),
                (0.022331162356015, _st(0.978350706908227, 0.295830776620995)),
                (0.055594877793785, _st(0.901672714410389, 0.541983037327871)),
                (0.006049054506376, _st(1.007018449383116, 0.669414798783936)),
                (0.024839207949609, _st(0.945161453573471, 0.829501421477824)),
                ]
        else:
            assert index == 10
            self.degree = 21
            data = [
                (0.019503841092684, _symm_r_0(0.980883148832881)),
                (0.089012127744268, _symm_r_0(0.678152700336576)),
                (0.114568584702749, _symm_r_0(0.240599282275864)),
                (0.007463627359106, _symm_s(0.965176994929162)),
                (0.050585943594705, _symm_s(0.749698539312765)),
                (0.074613865184212, _symm_s(0.568983925500818)),
                (0.023501091310143, _st(0.971086142843168, 0.355832132274584)),
                (0.011588562644144, _st(0.983453947854968, 0.645588139196562)),
                (0.023073245798171, _st(0.933927707027213, 0.821920249234369)),
                (0.001570221774472, _st(1.014086498915039, 0.862185099566557)),
                (0.049102258016277, _st(0.877914842155496, 0.168914072450263)),
                (0.042512352239126, _st(0.882246882640128, 0.568113580166780)),
                (0.067270936863160, _st(0.741324453314596, 0.371360260002223)),
                (0.103507336515645, _st(0.469570217710647, 0.237333359193547)),
                ]

        self.points, self.weights = untangle(data)
        return


def _c():
    return numpy.array([[0, 0]])


def _symm_r_0(r):
    return numpy.array([
        [+r, 0],
        [-r, 0],
        [0, +r],
        [0, -r],
        ])


def _symm_s(s):
    return numpy.array([
        [+s, +s],
        [-s, +s],
        [+s, -s],
        [-s, -s],
        ])


def _st(s, t):
    return numpy.array([
        [+s, +t],
        [-s, +t],
        [+s, -t],
        [-s, -t],
        [+t, +s],
        [-t, +s],
        [+t, -s],
        [-t, -s],
        ])
